"""
AI模型服务模块

提供不同AI模型的统一接口
"""

import logging
from typing import Dict, Any, Optional
import requests
from abc import ABC, abstractmethod
import json

from src.core.config_manager import ConfigManager

logger = logging.getLogger(__name__)

class AIModel(ABC):
    """AI模型基类"""
    
    def __init__(self, config: Dict[str, Any], debug: bool = False):
        """
        初始化AI模型
        
        Args:
            config: 模型配置
            debug: 是否开启调试模式
        """
        self.config = config
        self.debug = debug
        self.logger = logger
        
        if self.debug:
            self.logger.setLevel(logging.DEBUG)
    
    @abstractmethod
    def generate_response(self, prompt: str) -> str:
        """
        生成AI回复
        
        Args:
            prompt: 用户输入文本
            
        Returns:
            AI生成的回复文本
        """
        pass

class OllamaModel(AIModel):
    """Ollama模型实现"""
    
    def __init__(self, config: Dict[str, Any], debug: bool = False):
        """
        初始化Ollama模型
        
        Args:
            config: 模型配置
            debug: 是否开启调试模式
        """
        super().__init__(config, debug)
        self.model_name = config.get("model_name", "llama3")
        self.temperature = config.get("temperature", 0.7)
        self.endpoint = config.get("endpoint", "http://localhost:11434/api/generate")
        self.max_tokens = config.get("max_tokens", 2000)
        self.logger.debug(f"Ollama模型初始化: {self.model_name}, 端点: {self.endpoint}")
        
    def generate_response(self, prompt: str) -> str:
        """
        生成AI回复
        
        Args:
            prompt: 用户输入文本
            
        Returns:
            AI生成的回复文本
        """
        self.logger.debug(f"向Ollama发送请求: {prompt[:50]}...")
        try:
            payload = {
                "model": self.model_name,
                "prompt": prompt,
                "temperature": self.temperature,
                "max_tokens": self.max_tokens
            }
            response = requests.post(self.endpoint, json=payload, timeout=60)
            self.logger.debug(f"Ollama响应状态: {response.status_code}, 内容: {response.text[:500]}")
            response.raise_for_status()

            # 处理流式多行JSON
            lines = response.text.strip().splitlines()
            reply = ""
            for line in lines:
                try:
                    obj = json.loads(line)
                    if "error" in obj:
                        self.logger.error(f"Ollama返回错误: {obj['error']}")
                        return f"AI服务器错误: {obj['error']}"
                    reply += obj.get("response", "")
                except Exception as e:
                    self.logger.error(f"解析Ollama流式响应行失败: {e}, 行内容: {line}")
                    continue

            if not reply:
                self.logger.error(f"Ollama返回空响应: {response.text}")
                return "抱歉，AI无法生成回复。"
            return reply

        except requests.exceptions.RequestException as e:
            self.logger.error(f"Ollama请求失败: {e}")
            return "抱歉，无法连接到AI服务器。"
        except Exception as e:
            self.logger.error(f"生成AI回复时发生错误: {e}")
            return "抱歉，处理您的请求时出现了问题。"

class OpenAIModel(AIModel):
    """OpenAI模型实现"""
    
    def __init__(self, config: Dict[str, Any], debug: bool = False):
        """
        初始化OpenAI模型
        
        Args:
            config: 模型配置
            debug: 是否开启调试模式
        """
        super().__init__(config, debug)
        self.model_name = config.get("model_name", "gpt-3.5-turbo")
        self.api_key = config.get("api_key", "")
        self.temperature = config.get("temperature", 0.7)
        self.logger.debug(f"OpenAI模型初始化: {self.model_name}")
        
        # 检查API密钥
        if not self.api_key:
            self.logger.warning("未设置OpenAI API密钥")

        try:
            import openai
            self.client = openai.OpenAI(api_key=self.api_key)
        except ImportError:
            self.logger.error("请安装OpenAI Python包: pip install openai")
            raise
        
    def generate_response(self, prompt: str) -> str:
        """
        生成AI回复
        
        Args:
            prompt: 用户输入文本
            
        Returns:
            AI生成的回复文本
        """
        self.logger.debug(f"向OpenAI发送请求: {prompt[:50]}...")
        try:
            response = self.client.chat.completions.create(
                model=self.model_name,
                messages=[{"role": "user", "content": prompt}],
                temperature=self.temperature
            )
            
            response_text = response.choices[0].message.content
            
            if not response_text:
                self.logger.error(f"OpenAI返回空响应")
                return "抱歉，AI无法生成回复。"
                
            return response_text
            
        except Exception as e:
            self.logger.error(f"生成AI回复时发生错误: {e}")
            return "抱歉，处理您的请求时出现了问题。"

class MockAIModel(AIModel):
    """模拟AI模型，用于测试"""
    
    def __init__(self, config: Dict[str, Any], debug: bool = False):
        """
        初始化模拟AI模型
        
        Args:
            config: 模型配置
            debug: 是否开启调试模式
        """
        super().__init__(config, debug)
        self.logger.debug("模拟AI模型初始化")
        
    def generate_response(self, prompt: str) -> str:
        """
        生成AI回复
        
        Args:
            prompt: 用户输入文本
            
        Returns:
            AI生成的回复文本
        """
        self.logger.debug(f"模拟AI收到请求: {prompt}")
        return f"这是模拟AI的回复: 我收到了你的消息，内容是\"{prompt[:30]}...\"。这只是一个测试回复。"

class ModelFactory:
    """模型工厂类，用于创建不同类型的AI模型"""
    
    @staticmethod
    def create_model(config: Dict[str, Any], debug: bool = False) -> AIModel:
        """
        创建AI模型实例
        
        Args:
            config: 模型配置
            debug: 是否开启调试模式
            
        Returns:
            AI模型实例
            
        Raises:
            ValueError: 如果模型类型不支持
        """
        model_type = config.get("type", "mock").lower()
        
        if model_type == "ollama":
            return OllamaModel(config, debug)
        elif model_type == "openai":
            return OpenAIModel(config, debug)
        elif model_type == "mock":
            return MockAIModel(config, debug)
        else:
            raise ValueError(f"不支持的AI模型类型: {model_type}") 